package ua.at.tsvetkov.samizdat.data;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.lang.ref.SoftReference;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

import ua.at.tsvetkov.samizdat.Const;
import ua.at.tsvetkov.samizdat.R;
import ua.at.tsvetkov.samizdat.activities.AcStartScreen;
import ua.at.tsvetkov.samizdat.database.ContentProviderSamizdat;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.AsyncTask;
import ua.at.tsvetkov.util.Log;

public class AsyncTaskBooks extends AsyncTask<Void, Integer, Void> {

	private Context					context;
	private NotificationManager	notificationManager;

	private ArrayList<String>		genresCollection;

	private float						allLineSize;
	private float						lineCounter;
	private int							innerCounter;

	private int							currentProgress	= -1;
	private int							NOTIFICATION		= R.string.SRV_BOOKS_STARTED;
	private int							secondsLeft;
	private int							bulkInsertCounter	= 0;
	
	private UpdateTimeTask			timerTask;

	public AsyncTaskBooks(Service context) {
		this.context = context;
		notificationManager = (NotificationManager) ((Service) context).getSystemService(Context.NOTIFICATION_SERVICE);
	}

	@Override
	protected void onPreExecute() {
		super.onPreExecute();
		genresCollection = new ArrayList<String>();

		Cursor cursor = context.getContentResolver().query(Uri.parse(ContentProviderSamizdat.GENRE_CONTENT_URI + "/"), null, null, null, null);
		cursor.moveToFirst();
		if (cursor.getCount() != 0) {
			do {
				genresCollection.add(cursor.getString(1));
			} while (cursor.moveToNext());
		}

	}

	@Override
	protected Void doInBackground(Void... params) {

		BufferedReader in = null;
		try {
			HttpURLConnection connection;
			URL url = new URL(Url.getBooksUrlWithCounter());
			connection = (HttpURLConnection) url.openConnection();
			connection.setConnectTimeout(Const.TIMEOUT * 15 * 10);
			connection.setRequestMethod("GET");
			connection.setRequestProperty("Content-Type", "text/plain; charset=utf-8");
			connection.setRequestProperty("User-Agent", "Android reader");
			in = new BufferedReader(new InputStreamReader(connection.getInputStream(), Const.ENCODING), 12000);

			ContentValues[] valuesArray = new ContentValues[6000];
			// ContentValues bookValue;
			lineCounter = 0;
			innerCounter = 0;
			allLineSize = 0;
			Calendar calendar = Calendar.getInstance();
			long startTime = calendar.getTimeInMillis();

			while (true) {

				SoftReference<ContentValues> bookValue = new SoftReference<ContentValues>(new ContentValues());
				innerCounter++;
				lineCounter++;
				String[] stsWR = split(in.readLine(), 10);

				StringBuffer genresBuffer = new StringBuffer("");
				for (int i = 0; i < genresCollection.size(); i++) {
					genresBuffer.append("0");
				}

				if (stsWR == null) {
					context.getContentResolver().bulkInsert(ContentProviderSamizdat.BOOK_CONTENT_URI, cutNullFromArray(valuesArray));
					break; // exit from cycle
				}

				if (lineCounter == 1) {
					allLineSize = Integer.parseInt(stsWR[0]);
					innerCounter = 0;
					continue;
				}

				if (stsWR.length == 10) {
					bookValue.get().put(Const.OBJECT, stsWR[0]);
					bookValue.get().put(Const.AUTHOR, stsWR[1]);
					// bookValue.get().put(Const.TITLE, removeHtmlTag(removeSpaces(stsWR[2])));
					bookValue.get().put(Const.TITLE, removeHtmlTag(stsWR[2]).trim());
					// bookValue.get().put(Const.TITLE, removeSpaces(stsWR[2]));
					// bookValue.get().put(Const.TITLE, stsWR[2]);
					bookValue.get().put(Const.TYPE, stsWR[3]);
					bookValue.get().put(Const.SIZE, stsWR[4]);
					try {
						if (stsWR[5].length() != 0) {
							SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy");
							Date date = format.parse(stsWR[5]);
							bookValue.get().put(Const.DATE, date.getTime());
						} else {
							bookValue.get().put(Const.DATE, 0);
						}
					} catch (ParseException ex) {
						bookValue.get().put(Const.DATE, 0);
					}

					try {
						if (stsWR[6].length() == 0) {
							bookValue.get().put(Const.BALL, 0);
						} else {
							bookValue.get().put(Const.BALL, Double.valueOf(stsWR[6]));
						}
					} catch (NumberFormatException ex) {
						bookValue.get().put(Const.BALL, 0);
					}
					bookValue.get().put(Const.COUNTER, stsWR[7]);
					bookValue.get().put(Const.ALL_JANR, stsWR[8]);
					bookValue.get().put(Const.ANNOT, stsWR[9]);

					for (String genre : stsWR[8].split(";")) {
						if (genresCollection.contains(genre)) {
							for (int i = 0; i < genresCollection.size(); i++) {
								if (genre.equals(genresCollection.get(i))) {
									genresBuffer.replace(i, i + 1, "1");
								}
							}
						}
					}
					bookValue.get().put(Const.BOOK_GENRES, genresBuffer.toString());
					bookValue.get().put(Const.BOOK_PATH, "");
				}

				valuesArray[(int) innerCounter - 1] = bookValue.get();
				genresBuffer = null;

				if (innerCounter == 6000) {
					context.getContentResolver().bulkInsert(ContentProviderSamizdat.BOOK_CONTENT_URI, valuesArray);
					bulkInsertCounter++;
					innerCounter = 0;
					valuesArray = null;
					bookValue = null;
					stsWR = null;
					valuesArray = new ContentValues[6000];
					Calendar endCalendar = Calendar.getInstance();
					long endTime = endCalendar.getTimeInMillis();
					publishProgress(-1, (int) (endTime - startTime));
				}

				float tmp = lineCounter / allLineSize * 100;
				publishProgress((int) tmp, -1);

			}
			connection.disconnect();
		} catch (Exception e) {
			Log.e(e);
		}
		Log.v("Download books Succsess");
		return null;
	}

	@Override
	protected void onProgressUpdate(Integer... progress) {
		if (progress[0] != currentProgress && progress[0] != -1) {
			currentProgress = progress[0];
			showNotification(currentProgress);
			Intent broadcastIntent = new Intent(Const.BROADCAST_MESSAGE).putExtra(Const.BOOKS_LOADING_PERCENTS, currentProgress);
			((Service) context).sendBroadcast(broadcastIntent);
		}

		if (progress[1] != null && progress[1] != -1) {

			float allBulkInsertCol = allLineSize / 6000;
			float completePart = bulkInsertCounter / allBulkInsertCol;
			float timeLeftMilis = ((progress[1] * (1 - completePart)) / completePart);
			int timeLeft = (int) (timeLeftMilis / 1000);

			// if (secondsLeft < timeLeft) {
			// timeBuffer = timeBuffer + 3;
			// timeLeft = timeLeft + timeBuffer;
			// } else {
			// timeLeft = timeLeft + timeBuffer;
			// }

			if (Math.abs(secondsLeft - timeLeft) > 40) {
				secondsLeft = timeLeft;
			}

			if (timerTask == null) {
				timerTask = new UpdateTimeTask();
				Timer timer = new Timer();
				timer.schedule(timerTask, 0, 1000);
			}
		}
	}

	@Override
	protected void onPostExecute(Void result) {
		super.onPostExecute(result);
		notificationManager.cancel(NOTIFICATION);
		((Service) context).stopSelf();
	}

	class UpdateTimeTask extends TimerTask {
		public void run() {
			secondsLeft = secondsLeft - 1;
			Intent broadcastIntent = new Intent(Const.BROADCAST_MESSAGE).putExtra(Const.END_TIME, secondsLeft).putExtra(Const.BOOKS_LOADING_PERCENTS, currentProgress);
			((Service) context).sendBroadcast(broadcastIntent);
			if (secondsLeft == 0) {
				cancel();
			}
		}
	}

	private void showNotification(int percents) {
		long when = System.currentTimeMillis();
		Notification notification = new Notification(R.drawable.samizdat_logo1, context.getString(R.string.BOOKS_DOWNLOADING), when);
		Intent intentStartScreen = new Intent(context, AcStartScreen.class);
		intentStartScreen.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
		PendingIntent contentIntent = PendingIntent.getActivity(context, 0, intentStartScreen, 0);
		notification.setLatestEventInfo(context, context.getString(R.string.BOOKS_DOWNLOADING), context.getString(R.string.ALREADY_DOWNLOADED) + " " + String.valueOf(percents) + "%", contentIntent);
		notificationManager.notify(NOTIFICATION, notification);
	}

	private static String[] split(String st, int count) {
		if (st != null) {
			String[] data = st.split("\\|");
			if (data.length == count) {
				return data;
			} else {
				String[] newData = new String[count];
				if (data.length < count)
					count = data.length;
				for (int i = 0; i < count; i++) {
					newData[i] = data[i];
				}
				for (int i = data.length; i < newData.length; i++) {
					newData[i] = "";
				}
				return newData;
			}
		} else {
			return null;
		}
	}

	private static ContentValues[] cutNullFromArray(ContentValues[] array) {
		ArrayList<ContentValues> tmpList = new ArrayList<ContentValues>();
		for (ContentValues currentContentValue : array) {
			if (currentContentValue != null) {
				tmpList.add(currentContentValue);
			}
		}
		return tmpList.toArray(new ContentValues[tmpList.size()]);
	}

	public static String removeHtmlTag(String src) {
		if (src == null)
			return null;
		return src.replaceAll("<.*?>|Ђ|ђ|&shy;", "").replaceAll("&nbsp;", " ").replaceAll("&quot;", "\"");
	}

}
